<body>

<h2>Why?</h2>
<div class="text">
Lately I was discussing about programming a flash-based multiuser game using sharedObjects.<br />
I'm not so fond of Flash so I thought: Flash can communicate with Javascript. So why not implement the game in Javascript and do only the multiplayer-communication in flash?<br />
I created jsSO to allow the clients to push data to the server and notify other clients immediately about changes.<br />
So this library allows programming of realtime games, chats etc.
</div>

<h2>How?</h2>
<div class="text">
There is no easy way to get a notification in Javascript on the client about changes on the server. 
So the solution is to use Flash and let it handle the update notifications.<br />
You have to install the Flash server from Adobe or se the <a href="http://osflash.org/red5" target="_blank">free java alternative: Red5</a> as in the example below.<br />
<br />
The data-transfer and the connection to the server are maintained by a simple embedded Flashmovie in your page.
The communication with other clients runs through the local Flashmovie and the Red5-Server.<br />
The data-flow between two clients looks like this:<br />
<br />
Javascript/jsSO <-> Flashmovie <-> Red5-Server <-> Flashmovie <-> Javascript/jsSO
</div>

<h2>Dependencies</h2>
<ul>
	<li>Javascript-Libraries: jquery + swfobject
	<li>Flash-Remoting-Server: red5 or similar
</ul>


<h1>Demos</h1>
<div class="text">
I'm currently working on improving jsSO, so if the demos are not working please come back later, or try them on your own red5-server! :)<br />
Open 2 Windows with the same demo and see how fast e.g. drawing in one window shows up on the other window!<br />
<a href="./simple.htm" target="_blank">Simple Button Example</a><br />
<a href="./draw.htm" target="_blank">Draw</a><br />
<a href="./chat.htm" target="_blank">Chat</a><br />
<a href="./call.htm" target="_blank">Call Server Side Functions</a><br />
</div>


<h1>Downoad / Repository</h1>
<h2>Releases</h2>
<div class="text">
2009-04-15: <a href="./jsSO-0.2.zip">Version 0.2</a>
* Allow calling functions on the server
* Event Handlers: e.g. detect connect/disconnect to rtmp-server
2009-02-24: <a href="./jsSO-0.1.zip">Version 0.1</a> (Inital release)
</div>
<h2>Source</h2>
<div class="text">
<a href="http://code.google.com/p/js-so/" target="_blank">SVN at code.google.com</a>
including all JavaScript examples and a Java red5-demo
</div>


<h1>Usage</h1>

<h2>Include the Javascripts</h2>
<pre>
&lt;script type="text/javascript" src="js/swfobject.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="js/jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="js/jsSO.js"&gt;&lt;/script&gt;
</pre>

<h2>Example Shared Object Usage</h2>
<pre lang="javascript">
// Connect to to a shared object Handler (SOSample) on the Red5-Server and
// use the objectName "draw". The objectName is identical to a namespace
// for your data or a chat-room.
// SOSample is the simplest shared object example of the Red5-server
jsSO.connect('rtmp://localhost/SOSample', 'draw');

// On button click set someVar in the shared object
$(':button').live('click', function(){
    jsSO.set('someVar', 'value');
});

// Listen to changes on the shared object
// event = A jquery event object
// updates = If a var is updated it is set in the updates-object.
//           See code below for usage
// data = All data in the object
jsSO.onSync(function(event, updates, data) {
    if (updates.someVar) {
        // someVar was updated
        console.log(data.someVar);
    }
});
</pre>

<h2>Other useful functions</h2>
<pre lang="javascript">
// get the current data of the shared object
var data = jsSO.getData();

// get the last updates on the shared object
var updates = jsSO.getUpdates();
</pre>

<h1 id="events">Event Handlers</h1>
<pre lang="javascript">
// events from jsSO:
// connection: onConnect, onConnectError, onDisconnect
// shared object sync: onSync
// one of these fires for each server-call: onCallResponse, onCallError

jsSO.onConnectError(function(event, code){
    // couldn't connect
});
jsSO.onDisconnect(function(event, code){
    // server disconnected me
});
jsSO.onCallError(function(event, error){
    // global error handler for all calls
});
</pre>

<h1 id="call">Calling Server-Side Methods</h1>
jsSO allows now calling Server-Side Methods.<br />
<ol>
	<li>connect() to the server, you only have to provide a rtmp-url if you do not neeed a shared-object</li>
	<li>jsSO calls the server-function getServiceList and creates a client-side jsSO.service object with all available methods.</li>
	<li>Calling a server-method is now as easy as: jsSO.service.helloWorld()</li>
	<li>To get results from the server i've borrowed the mochikit/dojo service syntax:<br />
		call addCallback() on the return value of the method to get the server-response or
		call addErrback() to get server errors.
	</li>
</ol>

<a href="./call.htm" target="_blank">Live Demo</a>
<h2>Example</h2>
<pre lang="javascript">
jsSO.connect('rtmp://pro-web.at/firstapp', {debug: true});

jsSO.onConnect(function(){

    // call function
    jsSO.service.add(2, 4).addCallback(function(ret){
        console.log(ret); // 6
    });
    // call alternative
    jsSO.call('add', 2, 4).addCallback(function(ret){
        console.log(ret); // 6
    });
    
    // call unknown function
    jsSO.call('unknown').addCallback(function(ret){
        // we don't get here
        console.log('OK');
    }).addErrback(function(error){
        // error object is printed
        console.log(error);
        
        // error.application = "org.red5.server.service.MethodNotFoundException"
        // error.code = "NetConnection.Call.Failed"
        // error.description = "Method unknown without arguments not found"
        // error.level = "error"
    });

    // call a function, which throws an exception
    jsSO.service.throwException().addCallback(function(ret){
        // we don't get here, because the server java code throws an exception
        console.log('OK');
    }).addErrback(function(error){
        // error object is printed
        console.log(error);
        
        // error.application = "example.remoteapp.TestException" (the exception class)
        // error.code = "NetConnection.Call.Failed"
        // error.description = "some error occured" (the exception description)
        // error.level = "error"
    });
});
</pre>
<h2>Server-Side: read all Services with the annotation @Service</h2>
<pre lang="java">
package jsso;
public class Application extends org.red5.server.adapter.ApplicationAdapter
{
    /**
     * Allows the javascript-client to retrieve a list of available methods
     */
    @Service
    public ArrayList<String> getServiceList() {
        ArrayList<String> serviceMethods = new ArrayList<String>();
        Method[] methods = this.getClass().getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Service.class)) {
                serviceMethods.add(method.getName());
            }
        }
        return serviceMethods;
    }
}
</pre>
<h2>Server-Side: the implemented Methods</h2>
<pre lang="java">
public class Application extends jsso.Application
{
    @Service
    public int add(int a, int b) {
        return a+b;
    }

    @Service
    public Object throwException() throws Exception {
        throw new TestException("some error occured");
    }
}
</pre>

<h1>Future Improvements</h1>
<ul>
    <li>Allow multiple connections with different objectNames to the Server
	<li>Automatic reconnect to sharedObject on connection loss
    <li>Fallback in case flashplugin is not present
</ul>

<!-- h1>For comments etc.</h1>
<div class="text">
please see the announcement on <a href="http://ajaxian.com/archives/jsso-flash-shared-objects-in-javascript" target="_blank">ajaxian.com</a>
</div -->

</body>